package task.nms;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.Map;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;



public class FindText extends NmsTask {

	@Override
	public void run(Map<String, String> propMap) {
		String schema = propMap.get("schema");
		String text = propMap.get("text");
		Pattern p = Pattern.compile(text);
		String[] tables;
		try {
			tables = getTablesInSchema(schema);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}

		for (String table : tables) {
			System.out.printf("processing table %s%n", table);
			String sql = String.format("select * from %s.%s", schema, table);
			try {
				Statement stmt = conn().createStatement();
				ResultSet rs = stmt.executeQuery(sql);
				ResultSetMetaData meta = rs.getMetaData();
				int cols = meta.getColumnCount();
				TreeSet<Integer> colSet = new TreeSet<Integer>();
				while (rs.next()) {
					for (int i=0 ; i<cols ; i++) {
						if (colSet.contains(i)) continue;
						String value = null;
						if (meta.getColumnType(i+1) == Types.CLOB) {
							Clob clob = rs.getClob(i+1);
							BufferedReader is = new BufferedReader(clob.getCharacterStream());
							for (int lineNo=1 ; ; i++) {
								String line = is.readLine();
								if (line == null) break;
								System.out.printf(" clob-line:%s%n", line);
								Matcher m = p.matcher(line);
								if (m.matches()) {
									colSet.add(i);
									String colName = meta.getColumnName(i+1);
									System.out.printf("Found '%s' in line %s of clob in table:%s column:%s%n", line, lineNo, table, colName);
									break;
								}
							}
							is.close();
						} else {
							try {
								value = rs.getString(i+1);
								if (value == null) continue;
								Matcher m = p.matcher(value);
								if (m.matches()) {
									colSet.add(i);
									String colName = meta.getColumnName(i+1);
									System.out.printf("Found '%s' in table:%s column:%s%n", value, table, colName);
								}
							} catch (NullPointerException e) {
								System.out.printf("%s on %s", e.getMessage(), value);
							}
						}
					}
				}
			} catch (SQLException e) {
				throw new RuntimeException(e);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}

	@Override
	public String getDescription() {
		String descr = "Find tables and rows containing a specified text pattern";
		return descr;
	}
	@Override
	public String[] propertyNames() {
		String[] props = { "schema", "text"};
		return props;
	}

}
